/**
 * 
 */
package smallChanges.statements;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

import net.sourceforge.pmd.ast.ASTCompilationUnit;
import smallChanges.Tokenization.TokenSet;

/**
 * API for extracting a ClassDeclaration wrapper class or a list of statements from 
 * a Java source file.
 * 
 * 
 * @author jspacco
 *
 */
public class ExtractStatements
{

    /**
     * Parse a source file and return a list of statements inside the class.
     * @param sourceVersion
     * @param reader
     * @return
     * @throws IOException
     */
//    static List<Statement> extractStatements(
//            String sourceVersion,
//            TokenSet tokenSet,
//            Reader reader)
//    throws IOException
//    {
//        List<ClassDeclaration> topLevelClasses=extractClassDeclaration(sourceVersion, tokenSet, reader);
//        return ClassDeclaration.flatten(topLevelClasses);
//    }
    
    /**
     * Parse a source file and return a list of 
     * statements inside the class.  This includes the class declaration header line,
     * field declarations, the static initializer, and methods.  Note that all statements
     * in the class are guaranteed to be in the resulting list, though the order is
     * not guaranteed to be the same as in the original file.
     * 
     * This method handles multiple classes declared in one file.
     * @param sourceVersion
     * @param filename
     * @return
     * @throws IOException
     */
//    public static List<Statement> extractStatements(
//            String sourceVersion,
//            String filename)
//    throws IOException
//    {
//        List<ClassDeclaration> topLevelClasses=extractClassDeclaration(sourceVersion, filename);
//        return ClassDeclaration.flatten(topLevelClasses);
//    }
    
    /**
     * Extract a ClassDeclaration object (basically a structured wrapper for the statements 
     * inside the class) from a Reader.
     * @param sourceVersion
     * @param tokenSet
     * @param reader
     * @return
     * @throws IOException
     */
    static ParsedSourceFile extractClassDeclaration(
            String filename,
            String sourceVersion,
            TokenSet tokenSet,
            Reader reader)
    throws IOException
    {
        final ASTCompilationUnit cu = ParseUtilities.parseToASTCompilationUnit(
                reader,
                sourceVersion);
        
        BlockStatementVisitor visitor=new BlockStatementVisitor(tokenSet);
        ParsedSourceFile sourceFile=new ParsedSourceFile();
        sourceFile.setFilename(new File(filename).getName());
        cu.jjtAccept(visitor, sourceFile);
        return sourceFile;
    }
    
    public static ParsedSourceFile extractClassDeclaration(
            String sourceVersion,
            Long fileID,
            Long transID,
            String filename)
    throws IOException
    {
        Reader r1=new BufferedReader(new FileReader(filename));
        TokenSet tokenSet=TokenSet.
            readTokenSet(r1, sourceVersion, fileID, transID);
        r1.close();
        
        Reader r2=new BufferedReader(new FileReader(filename));
        ParsedSourceFile parsedSourceFile=extractClassDeclaration(
                filename,
                sourceVersion, 
                tokenSet,
                r2);
        r2.close();
        return parsedSourceFile;
    }
    
    public static ParsedSourceFile extractClassDeclarationFromTextOfFile(
            String filename,
            String sourceVersion,
            String fileText,
            Long fileID,
            Long transID)
    throws IOException
    {
        Reader r1=new StringReader(fileText);
        TokenSet tokenSet=TokenSet.
            readTokenSet(r1, sourceVersion, fileID, transID);
        r1.close();
        
        Reader r2=new StringReader(fileText);
        ParsedSourceFile parsedSourceFile=extractClassDeclaration(
                filename,
                sourceVersion, 
                tokenSet,
                r2);
        r2.close();
        return parsedSourceFile;
    }
    
    
    public static ParsedSourceFile extractClassDeclaration(
            String sourceVersion,
            String filename)
    throws IOException
    {
        // use null for the fileID
        // this is OK for code that only uses files from the file
        // system and does not interact with the DB at all
        return extractClassDeclaration(
                sourceVersion, 
                null, 
                null,
                filename); 
    }
}
